package com.cy;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @Author 小李
 * @Date 2021/8/26 15:56
 */

/**
 * 当我们的主启动类使用时@EnableFeignClients，spring工程
 * 在启动时会扫描@FeignClient注解猫叔的接口，并基于接口创建其实现类（代理类）
 */
@EnableFeignClients
@SpringBootApplication
public class ScaConsumerApplication {
    //创建日志对象
    private static final Logger log=
             LoggerFactory.getLogger(ScaConsumerApplication.class);
    public static void main(String[] args) {
        SpringApplication.run(ScaConsumerApplication.class, args);
//        log.debug("==debug==");
//        log.info("==info==");
//        log.warn("==warn==");
//        log.error("==error==");


    }

    /**
     * springboot 工程中可以使用此对象调用第三方服务
     */
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    /**
     * @return
     * @Bean注解由spring提供，通常用于描述方法，用于高速spring框架 此方法的返回值要交给spring管理 ，类似@Controller
     * 这些注解一般描述的是类
     */

    @Bean
    @LoadBalanced
    public RestTemplate loadBalancedRestTemplate() {
        return new RestTemplate();
    }

    @Service
    public class ConsumerService{
        @SentinelResource("doConsumerService")
        public String doConsumerService(){
            //表示通过此方法访问指定资源，例如以后访问数据库
            return "do consumer service";
        }
    }

    @RestController
    public class ConsumerController {
        @Autowired
        private ConsumerService consumerService;
        @Value("${spring.application.name}")
        private String consumerName;
        @Autowired
        private RestTemplate restTemplate;

        @Autowired
        private RestTemplate loadBalancedRestTemplate;

        //http://localhost:8090/consumer/doRestEcho01
        @GetMapping("/consumer/doRestEcho01")
        public String doRestEcho01() {
            log.debug("/consumer/doRestEcho01  {}","doRestEcho01");
            //定义服务提供方的地址
            String url = "http://localhost:8081/provider/echo/" + consumerName;
            //调用服务提供方(sca-provider)
            return restTemplate.getForObject(url, String.class);
        }

        //loadBalancerClient对象在服务启动时底层已经帮我们创建好了
        @Autowired
        private LoadBalancerClient loadBalancerClient;

        @GetMapping("/consumer/doRestEcho02")
        public String doRestEcho02() {
            consumerService.doConsumerService();
            //基于服务采用一定的负载均衡算法获取服务实例
            ServiceInstance choose =
                    loadBalancerClient.choose("sca-provider");
            String ip = choose.getHost();
            int port = choose.getPort();
            //定义服务提供方的地址
            String url = "http://" + ip + ":" + port + "/provider/echo/" + consumerName;
            //假如不希望使用字符串拼接操作，可以使用如下方式（其中%s为占位符，传值时一定要注意顺序）
            // String url = String.format("http://%s:%s/provider/echo/%s", ip,port,consumerName);
            //调用服务提供方(sca-provider)
            return restTemplate.getForObject(url, String.class);
        }
        //创建一个实现自增自减功能的一个对象
        private AtomicLong atomicLong=new AtomicLong(0);
        @GetMapping("/consumer/doRestEcho03")
        public String doRestEcho03(HttpServletRequest request) throws InterruptedException {
            String header=request.getHeader("X-Request-Foo");
            System.out.println("header="+header);
            String paramValue=request.getParameter("foo");
            System.out.println("paramValue="+paramValue);
//            Cookie cookie=new Cookie("tokenId", "ABCD");
//            response.addCookie(cookie);
//            Long num=atomicLong.getAndIncrement();
//            if(num%2==0)
//            Thread.sleep(200);//模拟耗时操作
            //流控规则中的链路限流
            //consumerService.doConsumerService();
            //定义服务提供方的地址
            String url = String.format("http://%s/provider/echo/%s", "sca-provider", consumerName);

            //调用服务提供方(sca-provider)
            return loadBalancedRestTemplate.getForObject(url, String.class);
        }

        @GetMapping("/consumer/doRestEcho04")
        @SentinelResource
        public String doRestEcho04(Integer id,String name){
            return String.format("request id=%d,name=%s ",id,name);
            //%d,%s为字符串中的占位符，%d一般用做数字占位符，%s为字符串占位符

        }


    }
}